package cn.jetpiece.cloud.dict.app.modular.dict.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.jetpiece.cloud.dict.api.model.params.CreateCategoryParam;
import cn.jetpiece.cloud.dict.api.model.params.UpdateCategoryParam;
import cn.jetpiece.cloud.dict.api.model.result.CategoryResult;
import cn.jetpiece.cloud.dict.app.modular.dict.entity.Category;
import cn.jetpiece.cloud.dict.app.modular.dict.mapper.CategoryMapper;
import cn.jetpiece.cloud.dict.app.modular.dict.service.ICategoryService;
import cn.jetpiece.cloud.feign.instance.FeignInstance;
import cn.jetpiece.cloud.model.exception.ServiceException;
import cn.jetpiece.cloud.model.model.TreeSelectModel;
import cn.jetpiece.cloud.model.response.Result;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author hancp
 * @version 1.0
 * @description: 分类字典服务实现类
 * @date 2021-11-08 10:15:39
 */
@Service
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> implements ICategoryService {

//    @Autowired
//    private ICategoryRuleService categoryRuleService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addSysCategory(CreateCategoryParam param) {
        Category category = BeanUtil.toBean(param, Category.class);
        String categoryCode = category.getCode();
        Long categoryPid = ICategoryService.ROOT_PID_VALUE;
        String parentCode = null;
        if (ObjectUtil.isNotNull(category.getPid())) {
            categoryPid = category.getPid();
            //PID 不是根节点 说明需要设置父节点 hasChild 为1
            if (!ICategoryService.ROOT_PID_VALUE.equals(categoryPid)) {
                Category parent = baseMapper.selectById(categoryPid);
                parentCode = parent.getCode();
                if (!"1".equals(parent.getHasChild())) {
                    parent.setHasChild("1");
                    baseMapper.updateById(parent);
                }
            }
        }
        try {
            categoryCode = generateCagetoryCode(categoryPid, categoryCode, param.getFillRuleId());
        } catch (ServiceException e) {
            throw new ServiceException(e.getCode(), e.getErrorMessage());
        }
        category.setCode(categoryCode);
        category.setPid(categoryPid);
        baseMapper.insert(category);

    }

    @Override
    public void updateSysCategory(UpdateCategoryParam param) {
        Category category = BeanUtil.toBean(param, Category.class);
        if (Objects.isNull(category.getPid())) {
            category.setPid(ICategoryService.ROOT_PID_VALUE);
        } else {
            //如果当前节点父ID不为空 则设置父节点的hasChild 为1
            Category parent = baseMapper.selectById(category.getPid());
            if (parent != null && !"1".equals(parent.getHasChild())) {
                parent.setHasChild("1");
                baseMapper.updateById(parent);
            }
        }
        baseMapper.updateById(category);
    }

    @Override
    public List<TreeSelectModel> queryListByCode(String pcode) throws ServiceException {
        Long pid = ROOT_PID_VALUE;
        if (StrUtil.isNotEmpty(pcode)) {
            List<Category> list = baseMapper.selectList(new LambdaQueryWrapper<Category>().eq(Category::getCode, pcode));
            if (list == null || list.size() == 0) {
                throw new ServiceException(500, "该编码【" + pcode + "】不存在，请核实!");
            }
            if (list.size() > 1) {
                throw new ServiceException(500, "该编码【" + pcode + "】存在多个，请核实!");
            }
            pid = list.get(0).getId();
        }
        return baseMapper.queryListByPid(pid, null);
    }

    @Override
    public List<TreeSelectModel> queryListByPid(Long pid) {
        if (Objects.isNull(pid)) {
            pid = ROOT_PID_VALUE;
        }
        return baseMapper.queryListByPid(pid, null);
    }

    @Override
    public List<TreeSelectModel> queryListByPid(Long pid, Map<String, String> condition) {
        if (Objects.isNull(pid)) {
            pid = ROOT_PID_VALUE;
        }
        return baseMapper.queryListByPid(pid, condition);
    }

    @Override
    public Long queryIdByCode(String code) {
        return baseMapper.queryIdByCode(code);
    }

    @Override
    public String queryThirdPartCodeByCode(String code) {
        return baseMapper.queryThirdPartCodeByCode(code);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteSysCategory(String ids) {
        String allIds = this.queryTreeChildIds(ids);
        String pids = this.queryTreePids(ids);
        List<String> delIds = Arrays.asList(allIds.split(","));
        List<Long> delIds1 = delIds.stream().map(Long::parseLong).collect(Collectors.toList());
        //1.删除时将节点下所有子节点一并删除
        this.baseMapper.deleteBatchIds(delIds);
//        categoryRuleService.delBatchCategoryRule(delIds1);
        //2.将父节点中已经没有下级的节点，修改为没有子节点
        if (StrUtil.isNotEmpty(pids)) {
            LambdaUpdateWrapper<Category> updateWrapper = new UpdateWrapper<Category>().lambda().in(Category::getId, Arrays.asList(pids.split(","))).set(Category::getHasChild, "0");
            this.update(updateWrapper);
        }
    }

    /**
     * 查询节点下所有子节点
     *
     * @param ids
     * @return
     */
    private String queryTreeChildIds(String ids) {
        //获取id数组
        String[] idArr = ids.split(",");
        StringBuffer sb = new StringBuffer();
        for (String pidVal : idArr) {
            if (pidVal != null) {
                if (!sb.toString().contains(pidVal)) {
                    if (sb.toString().length() > 0) {
                        sb.append(",");
                    }
                    sb.append(pidVal);
                    this.getTreeChildIds(pidVal, sb);
                }
            }
        }
        return sb.toString();
    }

    /**
     * 查询需修改标识的父节点ids
     *
     * @param ids
     * @return
     */
    private String queryTreePids(String ids) {
        StringBuffer sb = new StringBuffer();
        //获取id数组
        String[] idArr = ids.split(",");
        for (String id : idArr) {
            if (id != null) {
                Category category = this.baseMapper.selectById(id);
                //根据id查询pid值
                Long metaPid = category.getPid();
                //查询此节点上一级是否还有其他子节点
                LambdaQueryWrapper<Category> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.eq(Category::getPid, metaPid);
                queryWrapper.notIn(Category::getId, Arrays.asList(idArr));
                List<Category> dataList = this.baseMapper.selectList(queryWrapper);
                if ((dataList == null || dataList.size() == 0) && !Arrays.asList(idArr).contains(metaPid) && !sb.toString().contains(metaPid + "")) {
                    //如果当前节点原本有子节点 现在木有了，更新状态
                    sb.append(metaPid).append(",");
                }
            }
        }
        if (sb.toString().endsWith(",")) {
            sb.deleteCharAt(sb.length() - 1);
        }
        return sb.toString();
    }

    /**
     * 递归 根据父id获取子节点id
     *
     * @param pidVal
     * @param sb
     * @return
     */
    private StringBuffer getTreeChildIds(String pidVal, StringBuffer sb) {
        LambdaQueryWrapper<Category> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Category::getPid, pidVal);
        List<Category> dataList = baseMapper.selectList(queryWrapper);
        if (dataList != null && dataList.size() > 0) {
            for (Category category : dataList) {
                if (!sb.toString().contains(category.getId() + "")) {
                    sb.append(",").append(category.getId());
                }
                this.getTreeChildIds(category.getId() + "", sb);
            }
        }
        return sb;
    }

    /**
     * 根据编码规则生成编码
     *
     * @param categoryPid
     * @param categoryCode
     * @param fillRuleId
     * @return
     */
    private String generateCagetoryCode(Long categoryPid, String categoryCode, String fillRuleId) throws ServiceException {
        JSONObject formData = new JSONObject();
        formData.put("pid", categoryPid);
        formData.put("code", categoryCode);
        //有编码规则
        if (!StrUtil.isBlank(fillRuleId)) {
            // 获取规则信息
//            Result<FillRuleResult> fillRuleResult = FeignInstance.getInstance().newInstance(FillRuleApi.class, "zysz-auth").queryById(fillRuleId);
//            FillRuleResult ruleResult = fillRuleResult.getResult();
//            if (ruleResult != null) {
//                Result<Object> objectResult = FeignInstance.getInstance().newInstance(FillRuleApi.class, "zysz-auth").executeByRuleCode(ruleResult.getRuleCode(), formData);
//                if (!objectResult.isSuccess()) {
//                    throw new ServiceException(500, objectResult.getResult().toString());
//                }
//                return (String) objectResult.getResult();
//            }
        }
        //采用默认分类生成规则
//        else{
//            if(StrUtil.isBlank(categoryCode)) {
//                Result<Object> objectResult = FeignInstance.getInstance().newInstance(FillRuleApi.class, "zysz-auth").executeByRuleCode(FillRuleConstant.DEFAULT_CATEGORY, formData);
//                if (!objectResult.isSuccess()) {
//                    throw new ServiceException(500, objectResult.getResult().toString());
//                }
//                return (String) objectResult.getResult();
//            }
//        }
        return categoryCode;
    }

    /**
     * 获取默认规则分类，如果以及设置过规则，不在属于默认
     *
     * @return
     */
    public List<Category> queryDefaultRuleCategory(Long pid) {
//        List<Long> ruleIds = categoryRuleService.getCategoryIds();
        LambdaQueryWrapper<Category> ruleQueryWrapper = new LambdaQueryWrapper<>();
        ruleQueryWrapper.eq(Category::getPid, pid);
        ruleQueryWrapper.isNotNull(Category::getCode);
//        if (CollectionUtil.isNotEmpty(ruleIds)) {
//            ruleQueryWrapper.notIn(Category::getId, ruleIds);
//        }
        ruleQueryWrapper.orderByDesc(Category::getCode);
        return this.list(ruleQueryWrapper);
    }

    /**
     * 获取当前节点的所有父节点信息
     *
     * @param id
     * @return
     */
    @Override
    public List<Category> queryParentById(Long id) {
        return this.baseMapper.queryParentById(id);
    }

    /**
     * 获取当前节点的所有父节点信息自定义规则信息
     *
     * @param id
     * @return
     */
    @Override
    public List<CategoryResult> queryParentRuleById(Long id) {
        return this.baseMapper.queryParentRuleById(id);
    }


    /**
     * 判断名称或者编码是否为空或者必填，编码与规则有关
     *
     * @param param
     * @return
     */
    public Result<String> checkDuplicate(UpdateCategoryParam param) {
        Result<String> result = new Result<>();
        Long id = Convert.toLong(param.getId());
        String name = param.getName();
        String code = param.getCode();
        String fillRuleId = param.getFillRuleId();
        //判断名称是否为空或者重复
        if (StrUtil.isBlank(name)) {
            return result.error500("分类名称不能为空");
        }
        if (StrUtil.isBlank(fillRuleId) && StrUtil.isBlank(code)) {
            return result.error500("分类编码不能为空");
        }
        //判断编码是否重复
        LambdaQueryWrapper<Category> queryWrapper = new LambdaQueryWrapper<>();
//        queryWrapper.eq(Category::getTenantId, TenantContext.getTenant());
        queryWrapper.eq(Category::getCode, code);
        List<Category> list = this.list(queryWrapper);
        if (CollectionUtil.isNotEmpty(list)) {
            Map<Long, Category> map = list.stream().collect(Collectors.toMap(Category::getId, Function.identity()));
            result.setSuccess(true);
            map.forEach((key, value) -> {
                if (!key.equals(id)) {
                    if (!StrUtil.isBlank(value.getCode()) && value.getCode().equals(code)) {
                        result.error500("分类编码已存在");
                    }
                }
            });
            return result;
        }
        result.setSuccess(true);
        return result;
    }

    /**
     * 判断名称或者编码是否为空或者必填，编码与规则有关
     *
     * @param id
     * @param code
     * @return
     */
    public Result<String> checkCodeDuplicate(Long id, String code) {
        Result<String> result = new Result<>();
        //判断名称\编码是否重复
        LambdaQueryWrapper<Category> queryWrapper = new LambdaQueryWrapper<>();
//        queryWrapper.eq(Category::getTenantId, TenantContext.getTenant());
        queryWrapper.eq(Category::getCode, code);
        Category category = this.getOne(queryWrapper);
        if (category != null) {
            // 同条记录
            if (category.getId().equals(id)) {
                result.setSuccess(true);
            } else { // 不同记录
                result.error500("分类编码已存在");
            }
        }
        result.setSuccess(true);
        return result;
    }

    /**
     * 通过ID获取所有的子分类信息
     *
     * @param id
     * @param isContainSelf 是否包含自己 { {1:包含 0:不包含}}
     * @return
     */
    @Override
    public List<Category> queryAllChildrenByPid(Long id, Integer isContainSelf) {
        return this.baseMapper.queryAllChildrenByPid(id, isContainSelf);
    }

    /**
     * 启用/禁用 包含子类
     *
     * @param id
     * @param flag {1:启用 0:禁用}
     * @return
     */
    @Override
    public List<Long> setEnableFlag(String id, Integer flag) {
        // 查找pid下的ID
        List<Category> categoryList = queryAllChildrenByPid(Convert.toLong(id), 1);
        if (CollectionUtil.isNotEmpty(categoryList)) {
            if (ObjectUtil.isNull(flag)) {
                flag = 0;
            }
            Integer finalFlag = flag;
            List<Long> idsList = categoryList.stream().filter(c -> (!finalFlag.equals(c.getEnableFlag()))).map(Category::getId).collect(Collectors.toList());
            if (CollectionUtil.isNotEmpty(idsList)) {
                LambdaUpdateWrapper<Category> updateWrapper = new LambdaUpdateWrapper<>();
                updateWrapper.set(Category::getEnableFlag, flag);
                updateWrapper.in(Category::getId, idsList);
                this.update(updateWrapper);
                return idsList;
            }
        }
        return new ArrayList<>();
    }


}
